package com.yuandian.management.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.bpm.common.security.util.SecurityUtils;
import com.yuandian.management.enums.ProbeFilterSyncEnum;
import com.yuandian.management.mapper.FilterBusinessDataMapper;
import com.yuandian.management.mapper.OriginalDataFilterMapper;
import com.yuandian.management.service.IProbeCaptureConfigService;
import com.yuandian.management.vo.OriginalDataFilterParams;
import com.yuandian.management.vo.OriginalDataFilterVo;
import com.yuandian.management.vo.OriginalFilterDataResultVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 探针捕获规则配置
 *
 * @author zhoutian
 * @date 2021/1/20 9:55
 */
@Service
public class IProbeCaptureConfigServiceImpl implements IProbeCaptureConfigService {
    @Autowired
    private OriginalDataFilterMapper originalDataFilterMapper;
    @Autowired
    private FilterBusinessDataMapper filterBusinessDataMapper;

    /**
     * 查询原始包捕获规则数据
     *
     * @param params 参数
     * @return Result
     */
    @Override
    public Page<OriginalDataFilterVo> queryOriginalDataFilterResultMap(OriginalDataFilterParams params) {
        List<OriginalDataFilterVo> resultList = new ArrayList<>();
        Page<OriginalDataFilterVo> page = new Page<>(params.getPageNum(), params.getPageSize());
        Page<OriginalDataFilterVo> dataFilterEoList = originalDataFilterMapper.queryFilterListByPage(page, params.getRuleName());
        if (CollectionUtils.isNotEmpty(dataFilterEoList.getRecords())) {
            // 查询当前已经捕获的条数且更新当前的数据
            List<Integer> filterIds = dataFilterEoList.getRecords().stream().map(OriginalDataFilterVo::getId).collect(Collectors.toList());
            List<OriginalFilterDataResultVo> originalFilterDataResultVo = filterBusinessDataMapper.countByFilterIds(filterIds);
            Map<Integer, OriginalFilterDataResultVo> countMap = originalFilterDataResultVo.stream().collect(Collectors.toMap(OriginalFilterDataResultVo::getFilterId, Function.identity()));
            //set已捕获条数
            for (OriginalDataFilterVo originalDataFilterEo : dataFilterEoList.getRecords()) {
                OriginalFilterDataResultVo countVo = countMap.get(originalDataFilterEo.getId());
                originalDataFilterEo.setCapturedCount(null == countVo ? null : countVo.getCount());
                resultList.add(originalDataFilterEo);
            }
			dataFilterEoList.setRecords(resultList);
        }
        return dataFilterEoList;
    }

    @Override
    public OriginalDataFilterVo findById(Integer id) {
        return originalDataFilterMapper.findById(id);
    }

    /**
     * 清理数据
     *
     * @param clearType 参数
     * @return Result
     */
    @Override
    public R clearData(Integer clearType) {
        //清理所有
        if (clearType == 1) {
            filterBusinessDataMapper.deleterAll();
            return R.ok();
        }
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date beginDate = new Date();
        Calendar date = Calendar.getInstance();
        date.setTime(beginDate);
        //清理三天前所有数据
        if (clearType == 2) {
            //设置系统当前时间的前三天

            date.set(Calendar.DATE, date.get(Calendar.DATE) - 3);
            filterBusinessDataMapper.deleterByTime(df.format(date.getTime()));
            return R.ok();
        }
        //清理七天前所有数据
        if (clearType == 3) {
            //设置系统当前时间的前七天
            date.set(Calendar.DATE, date.get(Calendar.DATE) - 7);
            filterBusinessDataMapper.deleterByTime(df.format(date.getTime()));
            return R.ok();
        }
        return R.failed("传入值为空");
    }

    /**
     * 保存原始包捕获规则
     *
     * @param params 参数
     * @return Result
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public R save(OriginalDataFilterVo params) {
        // 判断是新增还是编辑编辑暗转原有规则，不改变内部逻辑
        Integer id = params.getId();
        if (id != null) {
            //在这判断是否能进行编辑操作
            R result = this.judgeIfModify(id);
            if (result.getCode() != 0) {
                return result;
            }
            // 编辑需要实时流做出相应的操作
            params.setDr(ProbeFilterSyncEnum.DEL_FILTER.getType());
            originalDataFilterMapper.updateOriginalDataFilter(convertOriginalDataFilterToVo(params));
            OriginalDataFilterVo odf = new OriginalDataFilterVo();
            odf.setId(params.getId());
            odf.setStatus(ProbeFilterSyncEnum.NOW_SYNC.getType());
            originalDataFilterMapper.updateStatus(odf);
            odf.setEnable(ProbeFilterSyncEnum.NOT_EXECUTE.getType());
            originalDataFilterMapper.updateEnable(odf);
        } else {
            originalDataFilterMapper.addOriginalDataFilter(convertOriginalDataFilterToVo(params));
        }
        return R.ok();
    }

    /**
     * 修改 是否启用 or 逻辑删除
     *
     * @param idList   id集
     * @param isStatus 是否启用 0禁用 1启用',
     */
    @Override
    public R updateStatusByIds(List<Integer> idList, Integer isStatus) {
        // 对状态之间相互影响判断 是否可操作
        R result = this.judgeIfEnableOperate(idList);
        if (result.getCode() != 0) {
            return result;
        }
        // 更新数据
        Integer dr = ProbeFilterSyncEnum.STOP.getType().equals(isStatus) ?
                ProbeFilterSyncEnum.DEL_LOCAL_RULE.getType() : ProbeFilterSyncEnum.ADD_LOCAL_RULE.getType();
        originalDataFilterMapper.startOrStopStatus(idList, isStatus, dr);
        /*更新状态成功*/
        return R.ok();
    }

    /**
     * 删除探针数据过滤信息
     *
     * @param ids id集
     * @return Result
     */
    @Override
    public R deleteByIds(List<Integer> ids) {
        List<OriginalDataFilterVo> filterEos = originalDataFilterMapper.queryByIds(ids);
        //判断哪些可以删除(同步成功且 (执行完成或者未执行))
        for (OriginalDataFilterVo filterEo : filterEos) {
            Integer syncStatus = filterEo.getStatus();
            Integer executeStatus = filterEo.getEnable();
            Date syncTime = filterEo.getSyncTime();
            if (null != syncTime) {
                if (ProbeFilterSyncEnum.OK_SYNC.getType().equals(syncStatus) &&
                        !ProbeFilterSyncEnum.IN_EXECUTE.getType().equals(executeStatus)) {
                } else {
                    return R.failed(1001, "该规则当前不能被删除");
                }
            }
        }
        // 批量更新该配置为 dr = 1 和状态
        originalDataFilterMapper.logicDelByIds(ids, ProbeFilterSyncEnum.NOW_SYNC.getType());
        /*        删除成功,捕获数据将在同步成功后删除*/
        return R.ok();
    }

    /**
     * 保存原始包捕获规则
     *
     * @param ids 参数
     * @return Result
     */
    @Override
    public R syncFilterRule(List<Integer> ids) {
        // 查询原本的数据,下面需要判断是否是新建
        List<OriginalDataFilterVo> filterEos = originalDataFilterMapper.queryByIds(ids);
        for (OriginalDataFilterVo filterEo : filterEos) {
            // 新建/编辑同步规则只能是启用状态才行
            Integer startOrStopStatus = filterEo.getIsStatus();
            Integer syncStatus = filterEo.getStatus();
            Integer executeStatus = filterEo.getEnable();
            if (ProbeFilterSyncEnum.IN_EXECUTE.getType().equals(executeStatus)
                    || ProbeFilterSyncEnum.OK_EXECUTE.getType().equals(executeStatus)
                    || ProbeFilterSyncEnum.NOW_SYNC.getType().equals(syncStatus)
                    || ProbeFilterSyncEnum.STOP.getType().equals(startOrStopStatus)) {
                return R.failed(1001, "该规则状态不能同步");
            }
            Integer dr = ProbeFilterSyncEnum.ADD_LOCAL_RULE.getType();
            // 修改状态为重新同步，
            originalDataFilterMapper.updateFilterStatusByIds(ids, ProbeFilterSyncEnum.NOW_SYNC.getType(), null, dr);
        }
        return R.ok();
    }

    /**
     * 查询原始包捕获规则数据
     *
     * @return Result
     */
    @Override
    public List<Map<String, Object>> findName() {
        return originalDataFilterMapper.queryRuleNameMap();
    }

    /**
     * 编辑操作时判断状态组合
     *
     * @param id id
     * @return R
     */
    private R judgeIfModify(Integer id) {
        List<Integer> ids = new ArrayList<>(1);
        ids.add(id);
        List<OriginalDataFilterVo> filterEos = originalDataFilterMapper.queryByIds(ids);
        for (OriginalDataFilterVo filterEo : filterEos) {
            Integer executeStatus = filterEo.getEnable();
            Integer isStatus = filterEo.getIsStatus();
            Integer syncStatus = filterEo.getStatus();
            //  未执行 +正在同步
            if (ProbeFilterSyncEnum.NOW_SYNC.getType().equals(syncStatus)
                    && ProbeFilterSyncEnum.NOT_EXECUTE.getType().equals(executeStatus)) {
                return R.failed(1001, "该规则正在同步不能进行编辑！");
            }
            // 启用 + 同步完成+ 执行中
            if (ProbeFilterSyncEnum.IN_EXECUTE.getType().equals(executeStatus)
                    && ProbeFilterSyncEnum.START.getType().equals(isStatus)
                    && ProbeFilterSyncEnum.OK_SYNC.getType().equals(syncStatus)) {
                return R.failed(1001, "该规则正在执行,不能编辑！");
            }
        }
        return R.ok();
    }

    /**
     * 判断是否可以进行启用停用操作
     *
     * @param idList ids
     */
    private R judgeIfEnableOperate(List<Integer> idList) {
        // 查询
        List<OriginalDataFilterVo> filterEos = originalDataFilterMapper.queryByIds(idList);
        for (OriginalDataFilterVo filterEo : filterEos) {
            Integer executeStatus = filterEo.getEnable();
            Integer isStatus = filterEo.getIsStatus();
            Integer syncStatus = filterEo.getStatus();
            //判断新建规则状态判断
            if (null == filterEo.getSyncTime()) {
                // 新建启用
                if (ProbeFilterSyncEnum.START.getType().equals(isStatus)) {
                    return R.failed(1001, "此规则目前不能进行启用/停用操作");
                }
            }
            // 当前是 启用+未执行+同步中
            if (ProbeFilterSyncEnum.NOT_EXECUTE.getType().equals(executeStatus)
                    && ProbeFilterSyncEnum.START.getType().equals(isStatus)
                    && ProbeFilterSyncEnum.NOW_SYNC.getType().equals(syncStatus)) {
                return R.failed(1001, "此规则目前不能进行启用/停用操作");
            }
            // 执行完成的不能再调整状态
            if (ProbeFilterSyncEnum.OK_EXECUTE.getType().equals(executeStatus)) {
                return R.failed(1001, "执行完成的规则不能再启用/停用");
            }
            // 当前是 停用+执行中+同步中
            if (ProbeFilterSyncEnum.IN_EXECUTE.getType().equals(executeStatus)
                    && ProbeFilterSyncEnum.STOP.getType().equals(isStatus)
                    && ProbeFilterSyncEnum.NOW_SYNC.getType().equals(syncStatus)) {
                return R.failed("此规则目前不能进行启用/停用操作");
            }
        }
        return R.ok();
    }


    /**
     * 对象转换
     *
     * @param odfvo 参数
     * @return OriginalDataFilterVo
     */
    private OriginalDataFilterVo convertOriginalDataFilterToVo(OriginalDataFilterVo odfvo) {
        OriginalDataFilterVo odf = new OriginalDataFilterVo();
        String username = SecurityUtils.getUser().getName();
        BeanUtils.copyProperties(odfvo, odf);
        if (!StringUtils.isEmpty(odfvo.getKeyword())) {
            String skeyword = JSONUtil.toJsonStr(odfvo.getKeyword()).substring(1, JSONUtil.toJsonStr(odfvo.getKeyword()).length() - 1);
            String keyw = skeyword.replace(":", "\\:");
            String keyword = keyw.replace(",", "\\,");
            odf.setKeyword(keyword);
        }
        if (!StringUtils.isEmpty(odfvo.getRequestIp())) {
            odf.setRequestIp(odfvo.getRequestIp().replace(",", "\\,"));
        }
        if (!StringUtils.isEmpty(odfvo.getResponseIp())) {
            odf.setResponseIp(odfvo.getResponseIp().replace(",", "\\,"));
        }
        if (StringUtils.isEmpty(odfvo.getStartTime())) {
            odf.setStartTime(null);
        }
        if (StringUtils.isEmpty(odf.getEndTime())) {
            odf.setEndTime(null);
        }
        if (!StringUtils.isEmpty(odfvo.getId())) {
            odf.setId(odfvo.getId());
        }
        if (!StringUtils.isEmpty(odfvo.getCaptureCount())) {
            odf.setCaptureCount(odfvo.getCaptureCount());
        }
        if (!StringUtils.isEmpty(odfvo.getCapturedCount())) {
            odf.setCapturedCount(odfvo.getCapturedCount());
        } else {
            odf.setCapturedCount(0);
        }
        if (StringUtils.isEmpty(odfvo.getId())) {
            odf.setEnable(0);
            odf.setStatus(0);
        }
        odf.setCreater(username);
        odf.setCreateTime(new Date());
        return odf;
    }


}
